package com.dorukdestan.p2pshare.network;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;

import com.dorukdestan.p2pshare.logger.Logger;
import com.dorukdestan.p2pshare.model.Constants;
import com.dorukdestan.p2pshare.model.DownloadingFile;
import com.dorukdestan.p2pshare.model.Protocol;
import com.dorukdestan.p2pshare.model.SearchResult;
import com.dorukdestan.p2pshare.storage.DownloadQueue;
import com.dorukdestan.p2pshare.storage.SearchResults;

public class FileTransferOperations {
	private static Logger logger;
	
	static{
		logger = new Logger(FileTransferOperations.class); 
	}
	
	public static void startNewDownload(String fileHash){
		logger.debug("Starting new downlad.");
		
		SearchResult searchResult = SearchResults.getSearchResults().get(fileHash);
		DownloadingFile downloadingFile = DownloadQueue.createNewDownload(fileHash, 
							searchResult.getLengthOfFile(),
							searchResult.getName(),
							searchResult.getPeerAddresses());
		
		new Thread(new DownloadProcess(downloadingFile)).start();
	}
	
	/**
	 * Creates a new thread to request a file chunk.
	 * 
	 * @param fileHash
	 * @param indexStart
	 * @param indexEnd
	 * @param peerAddress
	 */
	public static void requestFileChunk(String fileHash, long indexStart, long indexEnd, InetAddress peerAddress){
		// [fileHash] [fileIndexStart] [fileIdexEnd]
		String protocolQuery = 	Protocol.DOWNLOAD_FILE + 
								Protocol.DELIMINATOR_CHAR +
								fileHash +
								Protocol.DELIMINATOR_CHAR +
								indexStart +
								Protocol.DELIMINATOR_CHAR +
								indexEnd;

		new Thread(new RequestFileChunkProcess(protocolQuery, peerAddress)).start();
	}
	
	private static class RequestFileChunkProcess implements Runnable {
		
		private String query;
		private InetAddress peerAddress;
		
		public RequestFileChunkProcess(String dataToBeSent,
				InetAddress peerAddress) {
			this.query = dataToBeSent;
			this.peerAddress = peerAddress;
		}

		@Override
		public void run() {
			logger.debug("requsting chunk from " + peerAddress + " " + query);
			
			Socket socket = null;
			try{
				socket = new Socket(peerAddress, Constants.TCP_PORT_NUMBER);
				socket.setReuseAddress(true);
				DataOutputStream output = new DataOutputStream(
						socket.getOutputStream());
				output.writeBytes(query);
			}
			catch (Exception e) {
				logger.error(e);
			} finally{
				if(socket != null)
					try {
						socket.close();
					} catch (IOException e) {
						logger.error(e);
					}
			}
			
		}

	}
	
	
	/**
	 * Creates a new thread to send the file chunk.
	 * 
	 * @param peerAddress
	 * @param fileHash
	 * @param fileIndexStart
	 * @param fileIndexEnd
	 * @param fileLength 
	 */
//	public static void sendFile(InetAddress peerAddress,
//			String fileHash, int fileIndexStart, int fileIndexEnd){
//		
//		logger.info("preparing to send chunk");
//		
//		Long hashValue;
//		try {
//			hashValue = Long.parseLong(fileHash);
//		} catch (NumberFormatException e) {
//			logger.error(e);
//			return;
//		}
//		
//		String dataToBeSent = null;
//		
//		SharedFile file = FileOperations.searchByHash(hashValue);
//		byte[] data = new byte[(int) file.length()];
//		
//		dataToBeSent = getChunk(fileIndexStart, fileIndexEnd, data);
//		
//		String protocolQuery =	Protocol.SENDING_FILE +
//								Protocol.DELIMINATOR_CHAR +
//								fileHash + 
//								Protocol.DELIMINATOR_CHAR +
//								0 +//FIXME use real index
//								Protocol.DELIMINATOR_CHAR + 
//								dataToBeSent;
//		try {
//			new FileInputStream(file).read();
//			
//		} catch (FileNotFoundException e) {
//			logger.error(e);
//			return;
//		} catch (IOException e) {
//			logger.error(e);
//			return;
//		}
//		
////		new Thread(new sendFileProcess(peerAddress, protocolQuery)).start();
//	}
	
	private static String getChunk(int fileIndexStart, int fileIndexEnd, byte[] data) {
		
		byte[] chunk = null;
		try {
			int len = fileIndexStart - fileIndexEnd + 1;
			chunk = new byte[len];
			System.arraycopy(data, 0, chunk , fileIndexStart, len);
		} catch (Exception e) {
			logger.error(e);
		}
		
		return new String(chunk);
	}

//	private static class sendFileProcess implements Runnable{
//		private InetAddress peerAddress;
//		private String dataToBeSent;
//		
//		public sendFileProcess(InetAddress peerAddress, String dataToBeSent) {
//			this.peerAddress = peerAddress;
//			this.dataToBeSent = dataToBeSent;
//		}
//
//		@Override
//		public void run() {
//			logger.info("sending chunk");
//			Socket socket = null;
//			try {
//				socket = new Socket(peerAddress, Constants.TCP_PORT_NUMBER);
//				socket.setReuseAddress(true);
//				
//				DataOutputStream output = new DataOutputStream(socket.getOutputStream());
//				output.writeBytes(dataToBeSent);
//			} catch (Exception e) {
//				logger.error(e);
//			} finally{
//				if(socket != null)
//					try {
//						socket.close();
//					} catch (IOException e) {
//						logger.error(e);
//					}
//			}
//		}
//	}
}